home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Format / rfc934 / rfc934.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  8.0 KB  |  333 lines

  1. /* rfc934.c: rfc934 filter channel */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc934/RCS/rfc934.c,v 6.0 1991/12/18 20:21:02 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Format/rfc934/RCS/rfc934.c,v 6.0 1991/12/18 20:21:02 jpo Rel $
  9.  *
  10.  * $Log: rfc934.c,v $
  11.  * Revision 6.0  1991/12/18  20:21:02  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "util.h"
  19. #include "head.h"
  20. #include "qmgr.h"
  21. #include "q.h"
  22. #include "prm.h"
  23. #include "chan.h"
  24. #include "dr.h"
  25. #include <sys/stat.h>
  26. #include "sys.file.h"
  27.  
  28. extern char    *quedfldir;
  29. extern char     *chndfldir;
  30. extern void    sys_init(), err_abrt(), rd_end();
  31. CHAN         *mychan;
  32. char        *this_msg = NULL, *this_chan = NULL;
  33. extern int    err_fatal;
  34. int        first_failureDR;
  35.  
  36. static struct type_Qmgr_DeliveryStatus *process ();
  37. static int initialise ();
  38. static int security_check ();
  39. static void dirinit ();
  40. static struct type_Qmgr_DeliveryStatus *new_DeliveryStatus();
  41. static ADDR *getnthrecip ();
  42. static int filterMsg();
  43. static int doFilter();
  44. /*   */
  45. /* main routine */
  46.  
  47. main (argc, argv)
  48. int     argc;
  49. char    **argv;
  50. {
  51.     sys_init(argv[0]);
  52.     dirinit ();
  53. #ifdef PP_DEBUG
  54.     if (argc>1 && (strcmp(argv[1],"debug") == 0))
  55.         debug_channel_control(argc,argv,initialise,process,NULLIFP);
  56.     else
  57. #endif
  58.         channel_control (argc, argv, initialise, process,NULLIFP);
  59. }
  60.  
  61. /*   */
  62. /* routine to move to correct place in file system */
  63.  
  64. static void dirinit ()
  65. {
  66.     if (chdir (quedfldir) < 0)
  67.         err_abrt (RP_LIO, " Unable to change directory to '%s'",
  68.               quedfldir);
  69. }
  70.  
  71. /*   */
  72. /* channel initialise routine */
  73.  
  74. static int initialise (arg)
  75. struct type_Qmgr_Channel *arg;
  76. {
  77.     char *name;
  78.  
  79.     name = qb2str(arg);
  80.  
  81.     if ((mychan = ch_nm2struct(name)) == NULLCHAN) {
  82.         PP_OPER(NULLCP,
  83.                ("Chans/rfc934 : Channel '%s' not known",name));
  84.         if (name != NULL) free(name);
  85.         return NOTOK;
  86.     }
  87.  
  88.     /* check if a rfc934 channel */
  89.     if (name != NULL) free(name);
  90.     return OK;
  91. }
  92.  
  93. /*   */
  94. /* routine to check if allowed to rfc934 filter this message */
  95. static int security_check (msg)
  96. struct type_Qmgr_ProcMsg *msg;
  97. {
  98.     char *msg_file = NULL, *msg_chan = NULL;
  99.     int result;
  100.  
  101.     result = TRUE;
  102.     msg_file = qb2str (msg->qid);
  103.     msg_chan = qb2str (msg->channel);
  104.  
  105.     if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) !=0)) {
  106.         PP_LOG(LLOG_EXCEPTIONS,
  107.                ("Chans/rfc934 channel err: '%s'",msg_chan));
  108.         result = FALSE;
  109.     }
  110.     if (msg_file != NULL) free(msg_file);
  111.     if (msg_chan != NULL) free(msg_chan);
  112.     return result;
  113. }
  114.  
  115. /*   */
  116. /* routine called to do rfc934 filter */
  117.  
  118. static struct type_Qmgr_DeliveryStatus *process (arg)
  119. struct type_Qmgr_ProcMsg *arg;
  120. {
  121.     struct prm_vars    prm;
  122.     Q_struct    que;
  123.     ADDR        *sender = NULL;
  124.     ADDR        *recips = NULL;
  125.     int         rcount;
  126.     int        retval;
  127.     struct type_Qmgr_UserList     *ix;
  128.     ADDR                *adr;
  129.     char        *error;
  130.     bzero((char *)&prm,sizeof(prm));
  131.     bzero((char *)&que,sizeof(que));
  132.     first_failureDR = TRUE;
  133.  
  134.     delivery_init(arg->users);
  135.     delivery_setall(int_Qmgr_status_messageFailure);
  136.     
  137.     if (security_check(arg) != TRUE)
  138.         return deliverystate;
  139.  
  140.     if (this_msg != NULL) free(this_msg);
  141.     if (this_chan != NULL) free(this_chan);
  142.  
  143.     this_msg = qb2str(arg->qid);
  144.     this_chan = qb2str(arg->channel);
  145.  
  146.     PP_LOG(LLOG_NOTICE,
  147.            ("filtering msg '%s' through '%s'",this_msg, this_chan));
  148.  
  149.     if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) {
  150.         PP_LOG(LLOG_EXCEPTIONS,
  151.             ("Chans/rfc934 rd_msg err: '%s'",this_msg));
  152.         rd_end();
  153.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  154.                          "Can't read message");
  155.     }
  156.  
  157.     /* check each recipient for processing */
  158.     for (ix = arg->users; ix; ix = ix->next) {
  159.         error = NULLCP;
  160.         if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) {
  161.             PP_LOG(LLOG_EXCEPTIONS,
  162.                 ("Chans/rfc934 : failed to find recipient %d of msg '%s'",ix->RecipientId->parm, this_msg));
  163.  
  164.              delivery_setstate(ix->RecipientId->parm,
  165.                       int_Qmgr_status_messageFailure,
  166.                       "Unable to find specified recipient");
  167.             continue;
  168.         }
  169.  
  170.         switch (chan_acheck(adr, mychan, 1, NULL)) {
  171.             case OK:
  172.             if (filterMsg(this_msg,adr, &error) == NOTOK) {
  173.                 if (err_fatal == TRUE) {
  174.                     PP_LOG(LLOG_EXCEPTIONS,
  175.                            ("failed to flatten msg '%s' (FATAL)", 
  176.                         this_msg));
  177.                     set_1dr(&que, adr->ad_no, this_msg,
  178.                         DRR_CONVERSION_NOT_PERFORMED,
  179.                         DRD_CONTENT_SYNTAX_ERROR,
  180.                         (error == NULLCP) ? "Unable to flatten the message" : error);
  181.                     delivery_set(adr->ad_no,
  182.                             (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR);
  183.                     first_failureDR = FALSE;
  184.                 } else {
  185.                     PP_LOG(LLOG_EXCEPTIONS,
  186.                            ("Chans/rfc934 : failed to filter msg '%s' for recip '%d' on channel '%s'",this_msg, adr->ad_no, this_chan));
  187.                     delivery_setstate(adr->ad_no,
  188.                               int_Qmgr_status_messageFailure,
  189.                               (error == NULLCP) ? "Failed to flatten message" : error);
  190.                 }
  191.             } else {
  192.                 /* CHANGE update adr->ad_rcnt in struct and in file */
  193.                 adr->ad_rcnt++;
  194.                 wr_ad_rcntno(adr,adr->ad_rcnt);
  195.                 delivery_set(adr->ad_no,
  196.                          int_Qmgr_status_success);
  197.             }
  198.             break;
  199.             default:
  200.             break;
  201.         }
  202.         if (error != NULLCP)
  203.             free(error);
  204.     }
  205.     if (rp_isbad(retval = wr_q2dr(&que, this_msg))) {
  206.         PP_LOG(LLOG_EXCEPTIONS,
  207.                ("%s wr_q2dr failure '%d'",mychan->ch_name,retval));
  208.         delivery_resetDRs(int_Qmgr_status_messageFailure);
  209.     }
  210.     rd_end();
  211.     q_free (&que);
  212.     prm_free(&prm);
  213.     return deliverystate;
  214. }
  215.  
  216. /*   */
  217. static int filterMsg (msg,recip,perr)
  218. /* return OK if managed to filter msg through mychan for recip */
  219. char    *msg;
  220. ADDR    *recip;
  221. char    **perr;
  222. {
  223.     char    *origdir = NULL,
  224.             *newdir = NULL;
  225.     int    result = OK;
  226.     struct stat statbuf;
  227.  
  228.     if (qid2dir(msg, recip, TRUE, &origdir) != OK) {
  229.         PP_LOG(LLOG_EXCEPTIONS,
  230.                ("Chans/rfc934 original directory not found for recipient %d of message '%s'",recip->ad_no, msg));
  231.         *perr = strdup("Can't find source directory");
  232.         result = NOTOK;
  233.     }
  234.  
  235.     /* temporary change to get new directory name */
  236.     recip->ad_rcnt++;
  237.     if ((result == OK) 
  238.         && (qid2dir(msg, recip, FALSE, &newdir) != OK)) {
  239.         PP_LOG(LLOG_EXCEPTIONS,
  240.                ("Chans/rfc934 couldn't construct new directory for recipient '%d' of message '%s'",recip->ad_no, msg));
  241.         *perr = strdup("Can't construct destination directory");
  242.         result = NOTOK;
  243.     }
  244.     recip->ad_rcnt--;
  245.     
  246.     if ((result == OK)
  247.         && (stat(newdir, &statbuf) == OK)
  248.         && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
  249.         /* directory already exists and so filter already done */
  250.  
  251.         if (origdir != NULL) free(origdir);
  252.         if (newdir != NULL) free(newdir);
  253.         return OK;
  254.     }
  255.  
  256.     if ((result == OK) && (doFilter(origdir,newdir,msg, perr) != OK))
  257.         result = NOTOK;
  258.  
  259.     if (origdir != NULL) free(origdir);
  260.     if (newdir != NULL) free(newdir);
  261.     return result;
  262. }
  263.  
  264. /*   */
  265. static doFilter (orig, new, msg, perr)
  266. /* filters orig directory through mychan to new directory */
  267. char    *orig,
  268.     *new,
  269.     *msg,
  270.     **perr;
  271. {
  272.     char        tmpdir[MAXPATHLENGTH], buf[BUFSIZ];
  273.     int        result = OK;
  274.     struct stat     statbuf;
  275.  
  276.     (void) sprintf(tmpdir, "%s/tmp.%s", 
  277.                msg, mychan->ch_name);
  278.     
  279.     if (stat(tmpdir, &statbuf) == OK) {
  280.         char    *cmd_line;
  281.         /* exists so remove it */
  282.         cmd_line = malloc((unsigned) (strlen("rm -rf ") +
  283.                            strlen(tmpdir) + 1));
  284.         sprintf(cmd_line, "rm -rf %s", tmpdir);
  285.         system(cmd_line);
  286.         if (cmd_line != NULL) free(cmd_line);
  287.     }
  288.  
  289.     if (mkdir(tmpdir, 0777) != OK) {
  290.         PP_SLOG(LLOG_EXCEPTIONS, tmpdir,
  291.                ("Can't make directory"));
  292.         (void) sprintf (buf,
  293.                 "Failed to make temporary directory '%s'",
  294.                 tmpdir);
  295.         *perr = strdup(buf);
  296.         result = NOTOK;
  297.     }
  298.  
  299.     if (result == OK) {
  300.         /* filter from orig to tmpdir */
  301.         result = do_rfc934(orig,tmpdir,perr);
  302.         /* if success rename tmpdir to new */
  303.         if ((result == OK) && (rename(tmpdir,new) == -1)) {
  304.             PP_SLOG(LLOG_EXCEPTIONS, "rename",
  305.                 ("Can't rename directory '%s' to '%s'",
  306.                  tmpdir, new));
  307.             (void) sprintf (buf,
  308.                     "Failed to rename '%s' to '%s'",
  309.                     tmpdir,new);
  310.             *perr = strdup(buf);
  311.             result = NOTOK;
  312.         }
  313.  
  314.     }
  315.     return result;
  316. }
  317.        
  318. /*   */
  319. /* auxilary routines to extract from lists */
  320. static ADDR *getnthrecip(que, num)
  321. Q_struct    *que;
  322. int        num;
  323. {
  324.     ADDR *ix = que->Raddress;
  325.  
  326.     if (num == 0)
  327.         return que->Oaddress;
  328.     while ((ix != NULL) && (ix->ad_no != num))
  329.         ix = ix->ad_next;
  330.     return ix;
  331. }
  332.  
  333.